#ifndef		_NST_H_
#define		_NST_H_

#include "stdafx.h"

using namespace std;

// magic number "BM"
#define			BITMAP_ID			('B' + ('M'<<8))



// header byte type for RLE
const int		RLE_COMMAND		=	0;
const int		RLE_ENDOFLINE	=	0;
const int		RLE_ENDOFBITMAP	=	1;
const int		RLE_DELTA		=	2;

const int		BI_OS2			=	-1;


#ifdef WIN32
#include	<windows.h>
#else


// compression type
const int		BI_RGB			=	0;
const int		BI_RLE8			=	1;
const int		BI_RLE4			=	2;
const int		BI_BITFIELDS	=	3;

#pragma warning( disable : 4103 )



// --------------------------------------------
// tagBITMAPFILEHEADER - bitmap file header.
// --------------------------------------------

#pragma pack(2)

typedef struct tagBITMAPFILEHEADER		// bmfh
{
	unsigned int	bfType;				// magic number "BM"
	unsigned int	bfSize;				// file size
	unsigned int	bfReserved1;		// reserved
	unsigned int	bfReserved2;		// reserved
	unsigned int	bfOffBits;			// offset to bitmap data

} BITMAPFILEHEADER, *PBITMAPFILEHEADER;

#pragma pack(4)



// --------------------------------------------
// tagBITMAPCOREHEADER - bitmap core header.
// --------------------------------------------

typedef struct tagBITMAPCOREHEADER		// bmch
{
	unsigned int	bcSize;				// size of the structure
	unsigned int	bcWidth;			// image width
	unsigned int	bcHeight;			// image height
	unsigned int	bcPlanes;			// must be equal to 1
	unsigned int	bcBitCount;			// number of bits per pixel

} BITMAPCOREHEADER, *PBITMAPCOREHEADER;


// --------------------------------------------
// tagBITMAPCOREINFO - bitmap core info.
// --------------------------------------------

typedef struct tagBITMAPCOREINFO		// bmci
{
	BITMAPCOREHEADER	bmciHeader;		// size of the structure
	RGBTRIPLE			bcmiColors[1];	// color palette

} BITMAPCOREINFO, *PBITMAPCOREINFO;



// --------------------------------------------
// BITMAPFILEHEADER - bitmap info header.
// --------------------------------------------

typedef struct tagBITMAPINFOHEADER
{
	unsigned int	biSize;				// size of the structure
	int				biWidth;			// image width
	int				biHeight;			// image height
	unsigned int	biPlanes;			// must be equal to 1
	unsigned int	biBitCount;			// number of bits per pixel
	unsigned int	biCompression;		// compression type
	unsigned int	biSizeImage;		// size of data bitmap
	int				biXPelsPerMeter;	// number of pixels per meter on the X axis
	int				biYPelsPerMeter;	// number of pixels per meter on the Y axis
	unsigned int	biClrUsed;			// number of colors used
	unsigned int	biClrImportant;		// number of important colors
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

#endif	// WIN32

const  int blockSize    = 32;
const  int blockOverlap = 20;
const  int numCandidateQuiltBlocks = 100;

class NST
{
  public:

	NST(std::string);
	~NST();

  public:
	
	int bmp_width;
	int bmp_height;

	int quilted_bmp_width;
	int quilted_bmp_height;

	int bmp_size;

    std::string    bmp_filename ;
	
	char* source_texture_pixels1  ;
	char* source_texture_pixels2 ;

	char* source_texture_pixels3 ;
	char* source_texture_pixels4 ;
	char* source_texture_pixels5 ;
	char* quilted_texture_map;
	
	int*  canditate_points;
	int*  canditate_errors;
	int*  sorted_canditate_errors;
	
	int*  vertical_route;
	int*  horizontal_route;

  private:

	BITMAPFILEHEADER*   bmfh;			// bitmap file header
	BITMAPINFOHEADER*   bmih;			// bitmap info header (windows)
	BITMAPCOREHEADER*   bmch;			// bitmap core header (os/2)

	char*               buffer;		    // buffer storing the entire file
	int					bitCount;		// number of bits per pixel
	int					compression;	// compression type (rgb/rle)


  public:
	  
	void  RGBTOHSV();
	void  RGBTOHSV2(string name);
	void  RGBTOHSV3(string name);

	void  TRANSFER();
	void  COLOR();
	int   ERRORS(int fromx, int fromy, int tox ,int toy);
	int   PLACEMENTERROR(int fromx , int fromy , int tox , int toy);
    void  PASTESECTION(int fromx, int fromy, int tox ,int toy);
	void  PASTESECTIONS(int fromx, int fromy, int tox ,int toy);
	int   SORT();
	void  VERTICALCUT(int fromx, int fromy, int tox ,int toy);
	void  HORIZONTALCUT(int fromx, int fromy, int tox ,int toy);
int excute(std::string targetfile,std::string example,std::string bmp_filename) ;
};
int NST:: excute(std::string targetfile,std::string example,std::string bmp_filename) 
{   	
	//for(int tx = 0 ; tx< 33 ;tx++)
	{
		std::string  file= targetfile;
	//sprintf(file,"%Cd.bmp", tx);

	NST *qbmp = new NST(example);//example
	qbmp->RGBTOHSV();//open example image
	qbmp->RGBTOHSV2(file);//open target image
	//qbmp->RGBTOHSV3("cc.bmp");
	//qbmp->TRANSFER();
	qbmp->TRANSFER();
	//qbmp->COLOR();
	ifstream		file1;
    file1.open(file.c_str() , std::ios::in | std::ios::binary);
	if(file1.fail())
		return 1;
    char  *buffer1 = new char[54];
	file1.read(buffer1, 54);
    file1.close();
    ofstream		fileout; 
	string s1 =bmp_filename;
	//stringstream s;
	//s<<2;
	//s1.append("D");
	//s1.append("__");
	//s1.append(s.str());
	//s1.append(".bmp");
	fileout.open(s1.c_str(), std::ios::out | std::ios::binary);
    fileout.write(buffer1,54);
//	cout<<qbmp->bmp_height<<endl;
	for(int n = 0 ; n < qbmp->quilted_bmp_height  ; n++) 
	{
	   for(int m = 0 ; m < qbmp->quilted_bmp_width ; m++)
	   {
			fileout.put(qbmp->quilted_texture_map[4 * (n * qbmp->quilted_bmp_width + m)]);
			fileout.put(qbmp->quilted_texture_map[4 * (n * qbmp->quilted_bmp_width + m)+1]);
			fileout.put(qbmp->quilted_texture_map[4 * (n * qbmp->quilted_bmp_width + m)+2]);
	   }
	}
	qbmp->~NST();
    qbmp = NULL;
	fileout.close();
	
	cout<<"finish"<<endl;

	}
    return 0;
}
NST::NST(string  filename)
{
	bmp_filename =  filename;
}

void NST::COLOR()
{

     quilted_bmp_width = 800;
	 quilted_bmp_height= 600;

	 int quiltingHeight = quilted_bmp_height;
	 int quiltingWidth  = quilted_bmp_width;

	 canditate_points = new int[numCandidateQuiltBlocks*2];
	 canditate_errors = new int[numCandidateQuiltBlocks];
     sorted_canditate_errors = new int[numCandidateQuiltBlocks];


	 for (int quiltingLocationY = 0; quiltingLocationY < (quiltingHeight-0); quiltingLocationY += (1))
	 {
			for (int quiltingLocationX = 0; quiltingLocationX < (quiltingWidth-0); quiltingLocationX += (1))
			{
				/*for (int k = 0; k < numCandidateQuiltBlocks; k++)
				{
				     int x = rand()%(bmp_width-blockSize);
				     int y = rand()%(bmp_height-blockSize);

					 canditate_points[k*2]   = x; 
                     canditate_points[k*2+1] = y;

					 int errors = PLACEMENTERROR(x,y,quiltingLocationX, quiltingLocationY);
					
					 canditate_errors[k] = errors;
				     sorted_canditate_errors[k] = canditate_errors[k];
					 
				}*/

				SORT();

				int selectFromBestNCandidateQuiltBlocks = 1;
			   
				int oneToSelect = sorted_canditate_errors[selectFromBestNCandidateQuiltBlocks];
					
				int candidateIndex = 0;
					
				while (canditate_errors[candidateIndex] != oneToSelect) 
					candidateIndex++;
			
			    //cout<<canditate_errors[candidateIndex]<<endl;

				int selected_point_x = canditate_points[candidateIndex*2];
                int selected_point_y = canditate_points[candidateIndex*2+1];
                   
				//VERTICALCUT(selected_point_x,selected_point_y,quiltingLocationX,quiltingLocationY);
				//HORIZONTALCUT(selected_point_x,selected_point_y,quiltingLocationX,quiltingLocationY);

				//PASTESECTION(selected_point_x,selected_point_y,quiltingLocationX,quiltingLocationY);
			
				int r = (unsigned char)(source_texture_pixels1[3 * (quiltingLocationY * bmp_width + quiltingLocationX)+2]);
			    int g = (unsigned char)(source_texture_pixels1[3 * (quiltingLocationY * bmp_width + quiltingLocationX)+1]);
			    int b = (unsigned char)(source_texture_pixels1[3 * (quiltingLocationY * bmp_width + quiltingLocationX)]);

			    int r1 = (unsigned char)(quilted_texture_map[4 * (quiltingLocationY * bmp_width + quiltingLocationX)+2]);
			    int g1 = (unsigned char)(quilted_texture_map[4 * (quiltingLocationY * bmp_width + quiltingLocationX)+1]);
			    int b1 = (unsigned char)(quilted_texture_map[4 * (quiltingLocationY * bmp_width + quiltingLocationX)]);


		        int Y1 = 0.299*r1 + 0.587*g1 + 0.114*b1;
			    int I1 = 0.596*r1 - 0.274*g1 - 0.322*b1;
			    int Q1 = 0.212*r1 - 0.523*g1 + 0.312*b1;

			    int Y = 0.299*r + 0.587*g + 0.114*b;
			    int I = 0.596*r - 0.274*g - 0.322*b;
			    int Q = 0.212*r - 0.523*g + 0.312*b;

			    int R =  1*Y1 + 0.956*I + 0.621*Q;
		  	    int G =  1*Y1 - 0.272*I - 0.647*Q;
			    int B =  1*Y1 - 1.105*I + 1.072*Q;


		        if(R > 255)
				   R = 255;
			    if(G > 255)
				   G = 255;
			    if(B > 255)
				   B = 255;

			    if(R < 0)
				   R = 0;
			    if(G < 0)
				   G = 0;
			    if(B < 0)
				   B = 0;

			    quilted_texture_map[4 * (selected_point_y * quilted_bmp_width + selected_point_x)] = (unsigned char)(R);
                quilted_texture_map[4 * (selected_point_y * quilted_bmp_width + selected_point_x)] = (unsigned char)(G);
			    quilted_texture_map[4 * (selected_point_y * quilted_bmp_width + selected_point_x)] = (unsigned char)(B);
			}
	 }

}

void NST::TRANSFER()
{
	 quilted_bmp_width = 800;
	 quilted_bmp_height= 600;

	 int quiltingHeight = quilted_bmp_height;
	 int quiltingWidth  = quilted_bmp_width;

	 canditate_points = new int[numCandidateQuiltBlocks*2];
	 canditate_errors = new int[numCandidateQuiltBlocks];
     sorted_canditate_errors = new int[numCandidateQuiltBlocks];

    /* quilted_texture_map  = new char[quilted_bmp_width * quilted_bmp_height * 4];
     
	 for (int i = 0; i < quilted_bmp_width; i++)
	 {
			for (int j = 0; j < quilted_bmp_height; j++)
			{
                  quilted_texture_map[4 * (j * quilted_bmp_width + i)]   = char(0);
				  quilted_texture_map[4 * (j * quilted_bmp_width + i)+1] = char(0);
				  quilted_texture_map[4 * (j * quilted_bmp_width + i)+2] = char(0);
				  quilted_texture_map[4 * (j * quilted_bmp_width + i)+3] = char(0);
			}
	 }
	
	 for (int quiltingLocationY = 0; quiltingLocationY < (quiltingHeight-blockSize); quiltingLocationY += (blockSize-blockOverlap))
	 {
			for (int quiltingLocationX = 0; quiltingLocationX < (quiltingWidth-blockSize); quiltingLocationX += (blockSize-blockOverlap))
			{
				for (int k = 0; k < numCandidateQuiltBlocks; k++)
				{
				     int x = rand()%(bmp_width-blockSize);
				     int y = rand()%(bmp_height-blockSize);

					 canditate_points[k*2]   = x; 
                     canditate_points[k*2+1] = y;

					 canditate_errors[k] = PLACEMENTERROR(x,y,quiltingLocationX, quiltingLocationY);
				     sorted_canditate_errors[k] = canditate_errors[k];
				}

			    int selectFromBestNCandidateQuiltBlocks = 1;
			   
				int oneToSelect = sorted_canditate_errors[selectFromBestNCandidateQuiltBlocks];
					
				int candidateIndex = 0;
					
				while (canditate_errors[candidateIndex] != oneToSelect) 
					candidateIndex++;
			
				int selected_point_x = canditate_points[candidateIndex*2];
                int selected_point_y = canditate_points[candidateIndex*2+1];

				PASTESECTIONS(selected_point_x,selected_point_y,quiltingLocationX,quiltingLocationY);
			}
	 }*/

	 int id = 0;

     for (int quiltingLocationY = 0; quiltingLocationY < (quiltingHeight-0); quiltingLocationY += (blockSize-blockOverlap))
	 {
			for (int quiltingLocationX = 0; quiltingLocationX < (quiltingWidth-0); quiltingLocationX += (blockSize-blockOverlap))
			{
				for (int k = 0; k < numCandidateQuiltBlocks; k++)
				{
				     int x = rand()%(bmp_width-blockSize);
				     int y = rand()%(bmp_height-blockSize);

					 canditate_points[k*2]   = x; 
                     canditate_points[k*2+1] = y;

					 int errors = PLACEMENTERROR(x,y,quiltingLocationX, quiltingLocationY);
					
					 canditate_errors[k] = errors;
				     sorted_canditate_errors[k] = canditate_errors[k];

					 id++;
				}

				int bestIndex = SORT();

				//int selectFromBestNCandidateQuiltBlocks = 1;
			   
				//int oneToSelect = sorted_canditate_errors[selectFromBestNCandidateQuiltBlocks];
					
				int candidateIndex = 0;

				candidateIndex = bestIndex;

				int selected_point_x = canditate_points[candidateIndex*2];
                int selected_point_y = canditate_points[candidateIndex*2+1];
                   
				VERTICALCUT(selected_point_x,selected_point_y,quiltingLocationX,quiltingLocationY);
				HORIZONTALCUT(selected_point_x,selected_point_y,quiltingLocationX,quiltingLocationY);

				PASTESECTION(selected_point_x,selected_point_y,quiltingLocationX,quiltingLocationY);
				
			}
	 }

	 cout<<id<<endl;
}


//begin dynamicProgram
void NST::VERTICALCUT(int fromx, int fromy, int tox ,int toy)
{
	int* dynamicProgrammingMatrix = new int[blockOverlap*blockSize];

	for (int i = 0; i < blockOverlap ; i++)
	{
		for (int j = 0; j < blockSize; j++)
		{
            dynamicProgrammingMatrix[j*blockOverlap+i] = 0;
		}
	}

	int eij = 0;

	for (int j = 0; j < blockOverlap; j++)
	{
		int toX = tox+j;
		int toY = toy;

		int fromX = fromx+j;
		int fromY = fromy;

		dynamicProgrammingMatrix[0*blockOverlap+j] = ERRORS(fromX,fromY,toX,toY);
	}

	for (int i = 1; i < blockSize; i++)
	{
			
		int toX = tox;
		int toY = toy;

		int fromX = fromx;
		int fromY = fromy;

		eij = ERRORS(fromX+0, fromY+i ,toX+0, toY+i);
		//0	
		dynamicProgrammingMatrix[i*blockOverlap+0]
		= eij + min(dynamicProgrammingMatrix[(i-1)*blockOverlap+(0+1)], dynamicProgrammingMatrix[(i-1)*blockOverlap+(0)]);
		//overlap-1
		eij = ERRORS(fromX+(blockOverlap-1), fromY+i ,toX+(blockOverlap-1), toY+i);

		dynamicProgrammingMatrix[i*blockOverlap+(blockOverlap-1)]
		= eij + min(dynamicProgrammingMatrix[(i-1)*blockOverlap+(blockOverlap-2)], dynamicProgrammingMatrix[(i-1)*blockOverlap+(blockOverlap-1)]);
		
		//middle
		for (int j = 1; j < blockOverlap-1; j++)
		{
		   eij = ERRORS(fromX+j, fromY+i ,toX+j, toY+i);
					
		   dynamicProgrammingMatrix[(i)*blockOverlap+(j)]
		   = eij + min(min(dynamicProgrammingMatrix[(i-1)*blockOverlap+(j-1)], dynamicProgrammingMatrix[(i-1)*blockOverlap+j]), dynamicProgrammingMatrix[(i-1)*blockOverlap+(j+1)]);
		}
     
	}

	vertical_route = new int[blockSize];

	int currentIndex = 0;
	int min = 999999999;

	for (int i = 0; i < blockOverlap; i++)
	{
		if(dynamicProgrammingMatrix[(blockSize-1)*blockOverlap+i] < min)	
		{ 
			min = dynamicProgrammingMatrix[(blockSize-1)*blockOverlap+i]; 
		    currentIndex = i;
		}
	}

	vertical_route[blockSize-1] = currentIndex;

	for (int i = blockSize-2; i >= 0; i--)
	{
		if (currentIndex == 0)
		{
		   if (dynamicProgrammingMatrix[i*blockOverlap+currentIndex] > dynamicProgrammingMatrix[i*blockOverlap+(currentIndex+1)]) 
			currentIndex++;
		}
		else if (currentIndex == blockOverlap-1)
		{
		   if (dynamicProgrammingMatrix[i*blockOverlap+currentIndex] > dynamicProgrammingMatrix[i*blockOverlap+(currentIndex-1)]) 
			   currentIndex--;
		}
		else
		{
			min = min(min(dynamicProgrammingMatrix[i*blockOverlap+currentIndex], dynamicProgrammingMatrix[i*blockOverlap+(currentIndex-1)]), dynamicProgrammingMatrix[i*blockOverlap+(currentIndex+1)]);
			
			if (min == dynamicProgrammingMatrix[i*blockOverlap+(currentIndex-1)] && min < dynamicProgrammingMatrix[i*blockOverlap+(currentIndex)]) 
				currentIndex--;
			else if(min == dynamicProgrammingMatrix[i*blockOverlap+(currentIndex+1)] && min < dynamicProgrammingMatrix[i*blockOverlap+(currentIndex)]) 
				currentIndex++;
		}

		vertical_route[i] = currentIndex;
	}
}

void NST::HORIZONTALCUT(int fromx, int fromy, int tox ,int toy)
{
   int* dynamicProgrammingMatrix = new int[blockOverlap*blockSize];

	for (int i = 0; i < blockOverlap ; i++)
	{
		for (int j = 0; j < blockSize; j++)
		{
            dynamicProgrammingMatrix[j*blockOverlap+i] = 0;
		}
	}

	int eij = 0;

	for (int j = 0; j < blockOverlap; j++)
	{
		int toX = tox+j;
		int toY = toy;

		int fromX = fromx+j;
		int fromY = fromy;

		dynamicProgrammingMatrix[0*blockOverlap+j] = ERRORS(fromX,fromY,toX,toY);
	}

	for (int i = 1; i < blockSize; i++)
	{
			
		int toX = tox;
		int toY = toy;

		int fromX = fromx;
		int fromY = fromy;

		eij = ERRORS(fromX+i, fromY+0 ,toX+i, toY+0);
			
		dynamicProgrammingMatrix[i*blockOverlap+0]
		= eij + min(dynamicProgrammingMatrix[(i-1)*blockOverlap+(0+1)], dynamicProgrammingMatrix[(i-1)*blockOverlap+(0)]);
		
		eij = ERRORS(fromX+i, fromY+(blockOverlap-1) ,toX+i, toY+(blockOverlap-1));

		dynamicProgrammingMatrix[i*blockOverlap+(blockOverlap-1)]
		= eij + min(dynamicProgrammingMatrix[(i-1)*blockOverlap+(blockOverlap-2)], dynamicProgrammingMatrix[(i-1)*blockOverlap+(blockOverlap-1)]);
		
		for (int j = 1; j < blockOverlap-1; j++)
		{
		   eij = ERRORS(fromX+i, fromY+j ,toX+i, toY+j);
					
		   dynamicProgrammingMatrix[(i)*blockOverlap+(j)]
		   = eij + min(min(dynamicProgrammingMatrix[(i-1)*blockOverlap+(j-1)], dynamicProgrammingMatrix[(i-1)*blockOverlap+j]), dynamicProgrammingMatrix[(i-1)*blockOverlap+(j+1)]);
		}
     
	}

	horizontal_route = new int[blockSize];

	int currentIndex = 0;
	int min = 999999999;

	for (int i = 0; i < blockOverlap; i++)
	{
		if(dynamicProgrammingMatrix[(blockSize-1)*blockOverlap+i] < min)	
		{ 
			min = dynamicProgrammingMatrix[(blockSize-1)*blockOverlap+i]; 
		    currentIndex = i;
		}
	}

	 horizontal_route[blockSize-1] = currentIndex;

	for (int i = blockSize-2; i >= 0; i--)
	{
		if (currentIndex == 0)
		{
		   if (dynamicProgrammingMatrix[i*blockOverlap+currentIndex] > dynamicProgrammingMatrix[i*blockOverlap+(currentIndex+1)]) 
			currentIndex++;
		}
		else if (currentIndex == blockOverlap-1)
		{
		   if (dynamicProgrammingMatrix[i*blockOverlap+currentIndex] > dynamicProgrammingMatrix[i*blockOverlap+(currentIndex-1)]) 
			   currentIndex--;
		}
		else
		{
			min = min(min(dynamicProgrammingMatrix[i*blockOverlap+currentIndex], dynamicProgrammingMatrix[i*blockOverlap+(currentIndex-1)]), dynamicProgrammingMatrix[i*blockOverlap+(currentIndex+1)]);
			
			if (min == dynamicProgrammingMatrix[i*blockOverlap+(currentIndex-1)] && min < dynamicProgrammingMatrix[i*blockOverlap+(currentIndex)]) 
				currentIndex--;
			else if(min == dynamicProgrammingMatrix[i*blockOverlap+(currentIndex+1)] && min < dynamicProgrammingMatrix[i*blockOverlap+(currentIndex)]) 
				currentIndex++;
		}

		 horizontal_route[i] = currentIndex;
	}
}

int NST::SORT()
{
	
/*    
    int temp = 0;

	for (int i = 0; i < numCandidateQuiltBlocks ; i++)
	{
		for (int j = 0; j < numCandidateQuiltBlocks-1; j++)
		{
			if (sorted_canditate_errors[j] > sorted_canditate_errors[j+1]) 
			{
				temp = sorted_canditate_errors[j+1]; 
				sorted_canditate_errors[j+1] = sorted_canditate_errors[j]; 
				sorted_canditate_errors[j] = temp; 
			}
		}//for
	}//for
	
return 0;*/

	int min = sorted_canditate_errors[0];

	int bestIndex = 0;

	for (int i = 1; i < numCandidateQuiltBlocks ; i++)
	{
		if(sorted_canditate_errors[i] < min)
		{
			min = sorted_canditate_errors[i];

			bestIndex = i;
		}
	}

	return bestIndex;
	//cout<<"cccc:"<<bestIndex<<endl;
}

int NST::ERRORS(int fromx, int fromy, int tox ,int toy)
{
   if(tox >= quilted_bmp_width)
		tox = quilted_bmp_width -1;
   if(toy >= quilted_bmp_height)
		toy = quilted_bmp_height-1;

   //cout<<"f:"<<bmp_width<<endl;

   if(fromx >= bmp_width)
		fromx = bmp_width -1;
   if(fromy >= bmp_height)
		fromy = bmp_height-1;

   int B1 = (unsigned char)(quilted_texture_map[4 * (toy * quilted_bmp_width + tox)]);
   int B= (unsigned char)(source_texture_pixels1[3 * (fromy * bmp_width + fromx)]);
	 
   int G1 = (unsigned char)(quilted_texture_map[4 * (toy * quilted_bmp_width + tox)+1]);
   int G= (unsigned char)(source_texture_pixels1[3 * (fromy * bmp_width + fromx)+1]);
		
   int R1 = (unsigned char)(quilted_texture_map[4 * (toy * quilted_bmp_width + tox)+2]);
   int R =(unsigned char)(source_texture_pixels1[3 * (fromy * bmp_width + fromx)+2]);		
	    
   int A = (unsigned char)(quilted_texture_map[4 * (toy * quilted_bmp_width + tox)+3]);

   int A1 = 1;

   if (A == 0 || A1 == 0) return 0;
   int errorR = ((int)R - (int)R1) * ((int)R - (int)R1);
   int errorG = ((int)G - (int)G1) * ((int)G - (int)G1);
   int errorB = ((int)B - (int)B1) * ((int)B - (int)B1);

   return errorR + errorG + errorB;

}

void NST::PASTESECTION(int fromx, int fromy, int tox ,int toy)
{
	for (int i = 0; i < blockSize; i++)
	{
		for (int j = 0; j < blockSize; j++)
		{	
			int toX = tox+i;
			int toY = toy+j;

			int fromX = fromx+i;
			int fromY = fromy+j;
			
			if(toX >= quilted_bmp_width)
				toX = quilted_bmp_width -1;
			if(toY >= quilted_bmp_height)
				toY = quilted_bmp_height-1;

			if(fromX >= bmp_width)
		        fromX = bmp_width -1;
            if(fromY >= bmp_height)
		        fromY = bmp_height-1;

			if (j == horizontal_route[i] && i == vertical_route[j])
			{
				 int R = (unsigned char)(quilted_texture_map[4 * (toY * quilted_bmp_width + toX)]);
                 int R1= (unsigned char)(source_texture_pixels1[3 * (fromY * bmp_width + fromX)]);
	 
                 int G = (unsigned char)(quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+1]);
                 int G1= (unsigned char)(source_texture_pixels1[3 * (fromY * bmp_width + fromX)+1]);
		
                 int B = (unsigned char)(quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+2]);
                 int B1 =(unsigned char)(source_texture_pixels1[3 * (fromY * bmp_width + fromX)+2]);		
	    
                 float r = (0.5*R+0.5*R1);
				 float g = (0.5*G+0.5*G1);
				 float b = (0.5*B+0.5*B1);

				 if(r > 255)
					 r = 255;
				 if(g > 255)
					 g = 255;
				 if(b > 255)
					 b = 255;

			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)]   = char(r);
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+1] = char(g);
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+2] = char(b);		
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+3] = char(1);
			  
					
			}
			else if (j >= horizontal_route[i] && i >= vertical_route[j])
			{
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)]   = source_texture_pixels1[3 * (fromY * bmp_width + fromX)];
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+1] = source_texture_pixels1[3 * (fromY * bmp_width + fromX)+1];
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+2] = source_texture_pixels1[3 * (fromY * bmp_width + fromX)+2];
				 quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+3] = char(1);
				
				 /*
				 quilted_texture_map[4 * (toY * quilted_bmp_width + toX)]   = char(0);
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+1] = char(0);
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+2] = char(0);		
			     quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+3] = char(1);
				*/
			}		
		}
	}
}

void NST::PASTESECTIONS(int fromx, int fromy, int tox ,int toy)
{
	for (int i = 0; i < blockSize; i++)
	{
		for (int j = 0; j < blockSize; j++)
		{	
			int toX = tox+i;
			int toY = toy+j;

			int fromX = fromx+i;
			int fromY = fromy+j;		 	


			quilted_texture_map[4 * (toY * quilted_bmp_width + toX)]   = source_texture_pixels1[3 * (fromY * bmp_width + fromX)];
			quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+1] = source_texture_pixels1[3 * (fromY * bmp_width + fromX)+1];
			quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+2] = source_texture_pixels1[3 * (fromY * bmp_width + fromX)+2];		
			quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+3] = char(1);		
		}
	}
}

int NST::PLACEMENTERROR(int fromx , int fromy , int tox , int toy)
{	
   int totalError = 0;

   for (int i = 0; i < blockSize; i++)
   {
		for (int j = 0; j < blockSize; j++)
		{
			int toX = tox+i;
			int toY = toy+j;
			
			int fromX = fromx+i;
			int fromY = fromy+j;

			if(toX >= quilted_bmp_width)
				toX = quilted_bmp_width -1;
			if(toY >= quilted_bmp_height)
				toY = quilted_bmp_height-1;

			if(fromx >= bmp_width)
		        fromx = bmp_width -1;
            if(fromy >= bmp_height)
		        fromy = bmp_height-1;

			if (toX >= 0 && toY >= 0)
			{
					int toA = (unsigned char)(quilted_texture_map[4 * (toY * quilted_bmp_width + toX)+3]);

					if (toA > 0)
					{   //int avg = (avgR-avgR1)*(avgR-avgR1);
						totalError += ERRORS(fromX,fromY,toX,toY);
					}
			}
		}
	}

	return totalError;
}

void NST::RGBTOHSV()
{
	std::ifstream		file;  // file stream

	// read the entire file in the buffer
	file.open(bmp_filename.c_str(), std::ios::in | std::ios::binary );

	if(file.fail())
	{
		cout<<"file open failure"<<endl;
		exit(1);
	}

	file.seekg(0, std::ios::end);
	int flen = file.tellg();
	file.seekg(0, std::ios::beg);

	buffer = new char[flen + 1];
	file.read(buffer, flen);
    char *pBuff = buffer;

	file.close();

	// read the header
	bmfh = (BITMAPFILEHEADER *)pBuff;
	pBuff += sizeof(BITMAPFILEHEADER);

	// verify that it's a BITMAP file
	if(bmfh->bfType != BITMAP_ID)
	{
		delete [] buffer;
		buffer = NULL;
		cout<<"file open failure"<<endl;
		exit(1);
	}

	bmch = (BITMAPCOREHEADER *)pBuff;
	bmih = (BITMAPINFOHEADER *)pBuff;

	pBuff += sizeof(BITMAPINFOHEADER);

	bitCount	= bmih->biBitCount;
	compression	= bmih->biCompression;

	bmp_width  = bmih->biWidth;
	bmp_height = bmih->biHeight;

	// move the pixel data Pointer to the begening of bitmap data
	pBuff = buffer + (bmfh->bfOffBits * sizeof(char)); 

	cout<<bmp_width<<endl;
	cout<<bmp_height<<endl;

	source_texture_pixels1     = new char[bmp_width * bmp_height * 3];


	for(int j = 0 ; j < bmp_height  ; j++) 
	{
		for(int i = 0 ; i < bmp_width ; i++)
		{
           source_texture_pixels1[3 * (j * bmp_width + i)] =   *(pBuff++);
		   source_texture_pixels1[3 * (j * bmp_width + i)+1] = *(pBuff++);
		   source_texture_pixels1[3 * (j * bmp_width + i)+2] = *(pBuff++);
		}
	}

    bmp_size = bmp_width * bmp_height;
	
	delete [] buffer;
	buffer = NULL;
}

void NST::RGBTOHSV2(string name)
{
	std::ifstream		file;  // file stream

	// read the entire file in the buffer
	file.open(name.c_str(), std::ios::in | std::ios::binary );

	if(file.fail())
	{
		cout<<"file open failure"<<endl;
		exit(1);
	}

	file.seekg(0, std::ios::end);
	int flen = file.tellg();
	file.seekg(0, std::ios::beg);

	buffer = new char[flen + 1];
	file.read(buffer, flen);
    char *pBuff = buffer;

	file.close();

	// read the header
	bmfh = (BITMAPFILEHEADER *)pBuff;
	pBuff += sizeof(BITMAPFILEHEADER);

	// verify that it's a BITMAP file
	if(bmfh->bfType != BITMAP_ID)
	{
		delete [] buffer;
		buffer = NULL;
		cout<<"file open failure"<<endl;
		exit(1);
	}

	bmch = (BITMAPCOREHEADER *)pBuff;
	bmih = (BITMAPINFOHEADER *)pBuff;

	pBuff += sizeof(BITMAPINFOHEADER);

	bitCount	= bmih->biBitCount;
	compression	= bmih->biCompression;

	quilted_bmp_width  = bmih->biWidth;
	quilted_bmp_height = bmih->biHeight;

	// move the pixel data Pointer to the begening of bitmap data
	pBuff = buffer + (bmfh->bfOffBits * sizeof(char)); 

    quilted_texture_map  = new char[quilted_bmp_width * quilted_bmp_height * 4];

	for(int j = 0 ; j < quilted_bmp_height  ; j++) 
	{
		for(int i = 0 ; i < quilted_bmp_width ; i++)
		{
         
		   quilted_texture_map[4 * (j * quilted_bmp_width + i)]   = *(pBuff++);
		   quilted_texture_map[4 * (j * quilted_bmp_width + i)+1] = *(pBuff++);
		   quilted_texture_map[4 * (j * quilted_bmp_width + i)+2] = *(pBuff++);
		   quilted_texture_map[4 * (j * quilted_bmp_width + i)+3] = char(1);
		}
	}

    bmp_size = quilted_bmp_width * quilted_bmp_height;
	
	delete [] buffer;
	buffer = NULL;
}

void NST::RGBTOHSV3(string name)
{
	std::ifstream		file;  // file stream

	// read the entire file in the buffer
	file.open(name.c_str(), std::ios::in | std::ios::binary );

	if(file.fail())
	{
		cout<<"file open failure"<<endl;
		exit(1);
	}

	file.seekg(0, std::ios::end);
	int flen = file.tellg();
	file.seekg(0, std::ios::beg);

	buffer = new char[flen + 1];
	file.read(buffer, flen);
    char *pBuff = buffer;

	file.close();

	// read the header
	bmfh = (BITMAPFILEHEADER *)pBuff;
	pBuff += sizeof(BITMAPFILEHEADER);

	// verify that it's a BITMAP file
	if(bmfh->bfType != BITMAP_ID)
	{
		delete [] buffer;
		buffer = NULL;
		cout<<"file open failure"<<endl;
		exit(1);
	}

	bmch = (BITMAPCOREHEADER *)pBuff;
	bmih = (BITMAPINFOHEADER *)pBuff;

	pBuff += sizeof(BITMAPINFOHEADER);

	bitCount	= bmih->biBitCount;
	compression	= bmih->biCompression;

	bmp_width  = bmih->biWidth;
	bmp_height = bmih->biHeight;

	// move the pixel data Pointer to the begening of bitmap data
	pBuff = buffer + (bmfh->bfOffBits * sizeof(char)); 

    source_texture_pixels2  = new char[bmp_width * bmp_height * 3];

	for(int j = 0 ; j < bmp_height  ; j++) 
	{
		for(int i = 0 ; i < bmp_width ; i++)
		{      
		   source_texture_pixels2[3 * (j * bmp_width + i)]   = *(pBuff++);
		   source_texture_pixels2[3 * (j * bmp_width + i)+1] = *(pBuff++);
		   source_texture_pixels2[3 * (j * bmp_width + i)+2] = *(pBuff++);
		}
	}

    bmp_size = bmp_width * bmp_height;
	
	delete [] buffer;
	buffer = NULL;
}

NST::~NST()
{
 
}

#endif  //_NST_H_
